package com.horizon.im.imServer.server;

import com.horizon.im.common.codec.ProtoBufDecoder;
import com.horizon.im.common.codec.ProtobufEncoder;
import com.horizon.im.imServer.serverHandler.ChatRedirectHandler;
import com.horizon.im.imServer.serverHandler.LoginRequestHandler;
import com.horizon.im.imServer.serverHandler.RemoteNotificationHandler;
import com.horizon.im.imServer.serverHandler.ServerExceptionHandler;
import com.horizon.util.IOUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.net.InetSocketAddress;

//netty的服务端消息链接和处理
@Data
@Slf4j
@Service("ChatServer")
public class ChatServer {
    //服务端口
    @Value("8081")
    private int port;

    //nio方式接受链接和处理
    private EventLoopGroup bg;
    private EventLoopGroup wg;

    //启动引导器
    private ServerBootstrap b = new ServerBootstrap();

    @Autowired
    private LoginRequestHandler loginRequestHandler;

    @Autowired
    private ServerExceptionHandler serverExceptionHandler;

    @Autowired
    private RemoteNotificationHandler remoteNotificationHandler;

    @Autowired
    private ChatRedirectHandler chatRedirectHandler;

    public void run(){
        //链接监听线程组
        bg = new NioEventLoopGroup(1);
        //传输处理线程组
        wg = new NioEventLoopGroup();
        //1.设置bootstrap
        b.group(bg, wg);
        //2.设置channel类型
        b.channel(NioServerSocketChannel.class);
        //3.设置父通道选项
        b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        b.option(ChannelOption.SO_KEEPALIVE, true);

        //4.设置监听端口
        b.localAddress(new InetSocketAddress(IOUtil.getHostAddress(), port));

        //5.装配流水线
        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                // 管理pipeline中的Handler
                ch.pipeline().addLast("deCoder", new ProtoBufDecoder());
                ch.pipeline().addLast("enCoder", new ProtobufEncoder());
//                ch.pipeline().addLast("heartBeat", new HeartBeatServerHandler());
                // 在流水线中添加handler来处理登录,登录后删除
                ch.pipeline().addLast("login", loginRequestHandler);
                ch.pipeline().addLast("remoteNotificationHandler", remoteNotificationHandler);
//                ch.pipeline().addLast("chatRedirect", chatRedirectHandler);
                ch.pipeline().addLast("serverException", serverExceptionHandler);
            }
        });
    }
}
